import 'dart:convert';

import 'package:LifeMusic/Global.dart';
import 'package:LifeMusic/utils/toast.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';

String BASE_URL = "http://103.44.248.79:3000";

class HttpUtil {
  static HttpUtil instance;
  Dio dio;
  BaseOptions options;

  CancelToken cancelToken = CancelToken();

  static HttpUtil getInstance() {
    if (null == instance) instance = HttpUtil();
    return instance;
  }

  /*
   * config it and create
   */
  HttpUtil() {
    //BaseOptions、Options、RequestOptions 都可以配置参数，优先级别依次递增，且可以根据优先级别覆盖参数
    options = BaseOptions(
      //请求基地址,可以包含子路径
      baseUrl: BASE_URL,
      //连接服务器超时时间，单位是毫秒.
      connectTimeout: 10000,
      //响应流上前后两次接受到数据的间隔，单位为毫秒。
      receiveTimeout: 2000,
      //Http请求头.
      headers: {
        //do something
        "version": "1.0.0"
      },
      //请求的Content-Type，默认值是"application/json; charset=utf-8",Headers.formUrlEncodedContentType会自动编码请求体.
      contentType: Headers.formUrlEncodedContentType,
      //表示期望以那种格式(方式)接受响应数据。接受四种类型 `json`, `stream`, `plain`, `bytes`. 默认值是 `json`,
      responseType: ResponseType.plain,
    );

    dio = Dio(options);
    // //Cookie管理
    // dio.interceptors.add(CookieManager(CookieJar()));

    //添加拦截器
    dio.interceptors.add(InterceptorsWrapper(onRequest: (RequestOptions options) {
      print("==============请求之前 Start==============");
      print("请求地址:  ${options.uri.toString()}");
      print('请求参数:  ${options.queryParameters}');
      print("==============请求之前 End==============");
      return options; //continue
    }, onResponse: (Response response) {
      // print("==============响应之前===============");
      // Do something with response data
      // print("${response.data}");
      // 获取data 使用jsonDecode对data进行内连序列化得到Map<String, dynamic>  ->  使用模型类对map进行序列化
      Map<String, dynamic> resData = jsonDecode(response.data);
      if(resData["code"]==502||resData["code"]==501){
        print("==============进入响应拦截，拦截异常状态===============");
        throw DioError(type: DioErrorType.RESPONSE, response: response, error: 'ServiceError');
      }
      // print("==============响应之前===============");
      return  resData;// continue
    }, onError: (DioError e) {
      print("==============dio  响应错误===============");
      formatError(e);
      // Do something with response error
      return e; //continue
    }));
  }

  /*
   * get请求
   */
  get(url, {data, options, cancelToken}) async {
    Response response;
    try {
      response = await dio.get(url, queryParameters: data, options: options, cancelToken: cancelToken);
      print('=============GET 响应成功=============');
      print('get success---------${response.data}');
      print('=============GET 响应成功=============');
    } on DioError catch (e) {
      throw Exception(e);
      // formatError(e)
    }
    return response.data;
  }

  /*
   * post请求
   */
  post(url, {data, options, cancelToken}) async {
    Response response;
    try {
      response = await dio.post(url, queryParameters: data, options: options, cancelToken: cancelToken);
      Global.logger.d({
        "info": "=============POST 响应成功=============",
        "code": url,
        // "data": response.data,
      });
    } on DioError catch (e) {
      throw Exception(e);
      // formatError(e);
    }
    return response.data;
  }

  /*
   * 下载文件
   */
  downloadFile(urlPath, savePath) async {
    Response response;
    try {
      response = await dio.download(urlPath, savePath, onReceiveProgress: (int count, int total) {
        //进度
        print("$count $total");
      });
      print('downloadFile success---------${response.data}');
    } on DioError catch (e) {
      print('downloadFile error---------$e');
      formatError(e);
    }
    return response.data;
  }

  /*
   * error统一处理
   */
   formatError<T>(DioError e) {
     // if(e.response == null) {
     //   showToast('服务器错误', backgroundColor: Colors.red);
     //   return;
     // }

     Map<String, dynamic> errInfo = jsonDecode(e.response.data);
     print('formatError===========$errInfo');
    String msg=errInfo["msg"]??'';
    if (e.type == DioErrorType.CONNECT_TIMEOUT) {
       print("连接超时");
     } else if (e.type == DioErrorType.SEND_TIMEOUT) {
       print("请求超时");
     } else if (e.type == DioErrorType.RECEIVE_TIMEOUT) {
       print("响应超时");
     } else if (e.type == DioErrorType.RESPONSE) {
         if(errInfo["code"]==501){
            msg ="账户不存在";
          }else if(errInfo["code"]==400){
           msg='错误';
         }
     } else if (e.type == DioErrorType.CANCEL) {
       print("请求取消");
     } else {
       print("未知错误");
     }
     showToast(msg, backgroundColor: Colors.red);
     throw Exception(errInfo);
  }

  /*
   * 取消请求
   *
   * 同一个cancel token 可以用于多个请求，当一个cancel token取消时，所有使用该cancel token的请求都会被取消。
   * 所以参数可选
   */
  void cancelRequests(CancelToken token) {
    token.cancel("cancelled");
  }
}
